package com.citrix.gs.util;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.citrix.gs.kit.URLKit;
import com.citrix.gs.util.base.PerforceUtil;
import com.citrix.gs.util.beacon.BeaconCI;
import com.citrix.gs.util.beacon.BeaconServer;
import com.citrix.gs.util.common.Config;
import com.citrix.gs.util.common.SrcInfo;

/*
 * Send out email report after tool deployed 
 */

@SuppressWarnings("unused")
public class ReviewReport {
    
    private static Logger logger = LoggerFactory.getLogger(ReviewReport.class);
    
    private String [] errorCodes;
    private BeaconServer server;
    private BeaconCI ci;
    
    public BeaconCI getCi() {
        return ci;
    }

    public void setCi(BeaconCI ci) {
        this.ci = ci;
    }

    public ReviewReport(String [] errorCodes, BeaconServer server) {
        
        this.errorCodes = errorCodes;
        this.server = server;
    }
    
    public ReviewReport(String errorCode, BeaconServer server) {
        this(new String [] { errorCode }, server);
    }
    
    
    private int sumRemain(JSONObject statics) {
        return sumIssues(statics.getJSONObject("remain"));
    }
    
    private int sumFixed(JSONObject statics) {
        return sumIssues(statics.getJSONObject("fixed"));
    }
    
    private int sumIssues(JSONObject issues) {
        int sum = 0;
        Set<String> tags = issues.keySet();
        
        for(String tag : tags) {
            JSONObject tagIssues = issues.getJSONObject(tag);
            Set<String> codes = tagIssues.keySet();
            
            for(String code : codes) {
                if(isCheckCode(code)) {
                    sum += tagIssues.getIntValue(code);
                }
            }
        }
        
        return sum;
    }
    
    private boolean isCheckCode(String code) {
        
        for(String errorCode : errorCodes) {
            if(code.equals(errorCode)) return true;
        }
        
        return false;    
    }
    
    private String errorCodesStr() {
        String ret = "Error Code [";
        
        for(String errorCode : errorCodes) {
            ret += errorCode + ",";
        }
        
        return ret.substring(0, ret.length()-1) + "]";
    }
    
    //TODO: optimize the code to let it could be applied to multiple tools
    private String tool = "ResourceDetector";
    private String beaconHost = "nkggsportal.eng.citrite.net";
    
    public void setBeaconHost(String beaconHost) {
        this.beaconHost = beaconHost;
    }

    public void setTool(String tool) {
        this.tool = tool;
    }
    
    private String getViewParams(String repo) {
        
        JSONObject params = new JSONObject();
        JSONObject from = new JSONObject();
        
        SrcInfo srcInfo = ci.getLastSrcInfo(repo);
        if(srcInfo == null) return "";
        
        JSONArray range = new JSONArray();
        long revTs = srcInfo.getRevisionDate().getTime();
        range.add(revTs); // range from
        range.add(revTs); // range to
        
        
        from.put("repository", repo);
        from.put("range", range);
        from.put("type","revision");
        from.put("revision", srcInfo.getRevisionNo());
        
        if(errorCodes.length == 1) {
            from.put("code", errorCodes[0]);
        }
        
        params.put("from", from);
        
        JSONObject filters = new JSONObject();
        JSONArray codes = new JSONArray();
        
        for(String code : errorCodes) {
            JSONObject codeFilter = new JSONObject();
            codeFilter.put("id", code);
            codes.add(codeFilter);
        }
        
        filters.put("code", codes);
        params.put("filters", filters);
        
        String paraString = params.toJSONString();
        logger.info(paraString);
        
        return paraString;
    }
    
    private String getRepoViewLink(String id) {
        String viewUrlFormat = "http://%s/#/beacon/view/repository/%s";
        
        return "<a href=\"" + String.format(viewUrlFormat, beaconHost, id)
                + "\">"
                + id +"</a>";
    }
    
    private String getRevisionViewLink(String id) {
        String viewUrlFormat = "http://%s/#/beacon/view/issues/%s?params=%s";
        String viewUrl = String.format(viewUrlFormat, beaconHost, id, getViewParams(id));
        
        return "<a href=\"" + server.getShortLink(URLKit.encodeURIComponent(viewUrl)) 
                + "\">"
                + id +"</a>";
    }

    private String getDetailLink(String id) {
        String urlFormat = "%s/job/%s-%s/lastSuccessfulBuild/artifact/%sDetailedResult.csv";
        
        return "<a href=\"" + String.format(urlFormat, ci.getHostURL(), tool, id, tool)
                + "\">Download</a>";
    }
    
    
    private String getTableRecord(String id, int remain, int fixed) {
        return getTableRecord(id, RepoConfig.me().getOwer(id), remain, fixed);
    }
    
    private String getTableRecord(String id, String owner, int remain, int fixed) {
        return String.format("<tr>"
                + "<td>%s</td>"
                + "<td>%d</td>"
                + "<td>%d</td>"
                + "<td>%d</td>"
                + "<td>%s</td>"
                + "<td>%s</td>"
                + "<td></td>"
                + "</tr>", getRevisionViewLink(id), remain+fixed ,remain, fixed, 
                owner, getDetailLink(id));
    }
    
    
    // TODO: make the parameters for mail into configuration file
    private void sendHttpEmail(String message) {
        String host = "sinpmail.citrite.net";
        String port = "587";
        String mailFrom = "svcacct_gsnkg@citrix.com";
        String username = "svcacct_gsnkg";
        String password = "7eyuchXx";
 
        // outgoing message information
        String mailTo = "yu.zhou@citrix.com";
        String subject = "Review Report from OneDeploy";
        
        HtmlEmailSender mailer = new HtmlEmailSender();
        
        try {
            mailer.sendHtmlEmail(host, port, username, password, mailFrom, mailTo,
                    subject, message);
        } catch (Exception e) {
            logger.error("Send mail fail: ", e);
        }
        
    }
    
    public void send(){
        logger.info("Sending ...");
        try {
            StringBuilder msg = new StringBuilder("");
            msg.append("<b>Review report: "
                    + errorCodesStr() +"</b><br>"
                    + "<p>Data from " + server.getRestClient().getURL() + "</p><br>"
                    + "<table border='1'>"
                    + "<thead>"
                        + "<th>Repository</th>"
                        + "<th>Total</th>"
                        + "<th>Remain</th>"
                        + "<th>Fixed</th>"
                        + "<th>Owner</th>"
                        + "<th>Raw Result</th>"
                        + "<th>Reviewed?</th>"
                    + "</thead>"
                    + "<tbody>");
            
            JSONArray repoArray = server.getRepoArray();
            int size = repoArray.size();
            
            HashMap<String, String> ownerRecords = new HashMap<String, String>();
             
            for(int i=0; i<size; i++) {
                JSONObject repo = repoArray.getJSONObject(i);
                String repoId = repo.getString("_id");
                JSONObject statics = repo.getJSONObject("statics");
                int remain = sumRemain(statics);
                int fixed = sumFixed(statics);
                
                if(remain !=0 || fixed != 0) {
                    
                    String owner = RepoConfig.me().getOwer(repoId);
                    String record = getTableRecord(repoId, owner, remain, fixed);
                    if(ownerRecords.containsKey(owner)) {
                        String origin = ownerRecords.get(owner);
                        record = origin + record;
                    }
                    
                    ownerRecords.put(owner, record);
                }
            }
            
            Set<String> owners = ownerRecords.keySet();
            for(String owner : owners) {
                msg.append(ownerRecords.get(owner));
            }
            
            msg.append("</tbody></table>");
            
            sendHttpEmail(msg.toString());
            
        } catch (Exception e) {
            logger.error("Error: ", e);
        }
        
        
        logger.info("Sent");
    }
    
    public static void main(String[] args) throws URISyntaxException {
        
        BeaconServer beacon = new BeaconServer(new URI("http://nkggsportal.eng.citrite.net:1111/api/2/"));
        BeaconCI ci = new BeaconCI(Config.me().getTestCI());
        ReviewReport rr = new ReviewReport("2012", beacon);
        rr.setCi(ci);
        rr.send();

    }

}
